﻿using System;
using System.Linq;
using System.Windows.Forms;
using EasierRdp.Base;
using EasierRdp.Forms;
using EasierRdp.Models;

namespace EasierRdp.Util
{
    class EasierRdpEvents
    {
        public delegate void VoidDelegate();
        public delegate void ControlDelegate(RdpSession session);

        public static GroupDialog GroupDialog = new GroupDialog();
        public static ServerDialog ServerDialog = new ServerDialog();
        public static AddServerDialog AddServerDialog = new AddServerDialog();
        public static AddUserDialog AddUserDialog = new AddUserDialog();
        public static UserDialog UserDialog = new UserDialog();
        public static SettingDialog SettingDialog = new SettingDialog();

        public static Forms.EasierRdp MainForm { get; set; }
        #region events
        public static void AddGroup(object sender, EventArgs e)
        {
            GroupDialog.Existing = false;
            if (GroupDialog.Group != null)
            {
                GroupDialog.Group = GroupDialog.Group.Clone();
            }
            GroupDialog.GroupParent = GetMouseClickTargetModel<IGroupContainer>();
            if (DialogResult.OK == GroupDialog.ShowDialog(MainForm))
            {

            }
        }

        public static void AddServerRef(object sender, EventArgs e)
        {
            if (MainForm.SelectedNode.Tag is RdpUser)
            {
                AddServerDialog.User = GetMouseClickTargetModel<RdpUser>();
                AddServerDialog.Group = null;
            }
            else if (MainForm.SelectedNode.Tag is RdpGroup)
            {
                AddServerDialog.User = null;
                AddServerDialog.Group = GetMouseClickTargetModel<RdpGroup>();
            }

            if (DialogResult.OK == AddServerDialog.ShowDialog(MainForm))
            {

            }
        }

        public static void AddUserRef(object sender, EventArgs e)
        {
            if (MainForm.SelectedNode.Tag is RdpServer)
            {
                AddUserDialog.Server = GetMouseClickTargetModel<RdpServer>();
                AddUserDialog.Group = null;
            }
            else if (MainForm.SelectedNode.Tag is RdpGroup)
            {
                AddUserDialog.Server = null;
                AddUserDialog.Group = GetMouseClickTargetModel<RdpGroup>();
            }
            if (DialogResult.OK == AddUserDialog.ShowDialog(MainForm))
            {

            }
        }

        public static void AddServer(object sender, EventArgs e)
        {
            if (ServerDialog.Server != null)
            {
                ServerDialog.Server = ServerDialog.Server.Clone();
            }
            if (DialogResult.OK == ServerDialog.ShowDialog(MainForm))
            {
                
            }
        }

        public static void AddUser(object sender, EventArgs e)
        {
            if (UserDialog.User != null)
            {
                UserDialog.User = UserDialog.User.Clone();
            }
            if (DialogResult.OK == UserDialog.ShowDialog(MainForm))
            {
                
            }
        }

        public static void AddSetting(object sender, EventArgs e)
        {
            if (SettingDialog.Setting != null)
            {
                SettingDialog.Setting = SettingDialog.Setting.Clone();
            }
            if (DialogResult.OK == SettingDialog.ShowDialog(MainForm))
            {

            }
        }

        public static void EditGroup(object sender, EventArgs e)
        {
            GroupDialog.Group = GetMouseClickTargetModel<RdpGroup>();
            GroupDialog.Existing = true;
            if (DialogResult.OK == GroupDialog.ShowDialog(MainForm))
            {

            }
        }

        public static void EditSetting(object sender, EventArgs e)
        {
            SettingDialog.Setting = GetMouseClickTargetModel<RdpSetting>();
            if (DialogResult.OK == SettingDialog.ShowDialog(MainForm))
            {
                
            }
        }

        public static void EditUser(object sender, EventArgs e)
        {
            UserDialog.User = GetMouseClickTargetModel<RdpUser>();
            if (DialogResult.OK == UserDialog.ShowDialog(MainForm))
            {

            }
        }

        public static void EditServer(object sender, EventArgs e)
        {
            ServerDialog.Server = GetMouseClickTargetModel<RdpServer>();
            if (DialogResult.OK == ServerDialog.ShowDialog(MainForm))
            {

            }
        }

        public static void SetDefault(object sender, EventArgs e)
        {

        }

        public static void ConnectWithDefault(object sender, EventArgs e)
        {
            var setting = (RdpSetting)((MenuItem)sender).Tag;
            if (MainForm.SelectedNode.Tag is RdpServer)
            {
                var server = GetMouseClickTargetModel<RdpServer>();
                if (server.Users.Count > 0)
                {
                    AddSession((RdpUser)server.Users[0].Ref, server, setting);
                }
            }
            else if (MainForm.SelectedNode.Tag is RdpUser)
            {
                var user = GetMouseClickTargetModel<RdpUser>();
                if (user.Servers.Count > 0)
                {
                    AddSession(user, (RdpServer)user.Servers[0].Ref, setting);
                }
            }
        }

        public static void Connect(object sender, EventArgs e)
        {
            Connect(sender, e, null);
        }

        public static void ConnectWithSetting(object sender, EventArgs e)
        {
            var setting = (RdpSetting)((MenuItem) sender).Tag;
            var parent = ((MenuItem) sender).Parent;
            Connect(parent, e, setting);
        }

        public static void DisconnectSession(object sender, EventArgs e)
        {
            var session = GetMouseClickTargetModel<RdpSession>();
            session.Disconnect();
        }

        public static void RemoveGroup(object sender, EventArgs e)
        {
            var group = GetMouseClickTargetModel<RdpGroup>();
            var parent = GetMouseClickTargetParentModel<IGroupContainer>();
            {
                if(parent.Groups.Contains(group))
                {
                    parent.Groups.Remove(group);
                    RebindTreeView();
                }
            }
        }

        public static void RemoveSession(object sender, EventArgs e)
        {
            var session = GetMouseClickTargetModel<RdpSession>();
            RdpContext.RemoveSession(session);
            RebindTreeView();
        }

        public static void DisconnectAllSessions(object sender, EventArgs e)
        {
            foreach (var rdpSession in RdpContext.Sessions.Values)
            {
                rdpSession.Disconnect();
            }
        }

        public static void RemoveUser(object sender, EventArgs e)
        {
            var user = GetMouseClickTargetModel<RdpUser>();
            if (RdpContext.FindActive(user))
            {
                MessageBox.Show("This User has active sessions and cannot be remove now");
            }
            if (!RdpContext.FindRef(user)
                || DialogResult.OK == MessageBox.Show(MainForm, "The User is refered by some servers, remove it anyway?", "Confirm Deleting", MessageBoxButtons.OKCancel))
            {
                RdpContext.RemoveUser(user);
            }
            RebindTreeView();
        }

        public static void RemoveServer(object sender, EventArgs e)
        {
            var server = GetMouseClickTargetModel<RdpServer>();
            if (RdpContext.FindActive(server))
            {
                MessageBox.Show("This Server has active sessions and cannot be remove now");
            }
            if (!RdpContext.FindRef(server) || DialogResult.OK == MessageBox.Show(MainForm, "The Server is refered by some users, remove it anyway?", "Confirm Deleting", MessageBoxButtons.OKCancel))
            {
                RdpContext.RemoveServer(server);
            }
            RebindTreeView();
        }

        public static void RemoveSetting(object sender, EventArgs e)
        {
            var setting = GetMouseClickTargetModel<RdpSetting>();
            RdpContext.RemoveSetting(setting);
            RebindTreeView();
        }

        public static void RemoveServerRef(object sender, EventArgs e)
        {
            var serverRef = GetMouseClickTargetModel<RdpServerRef>();
            var user = GetMouseClickTargetParentModel<RdpUser>();
            if (user.Servers.Contains(serverRef))
            {
                user.Servers.Remove(serverRef);
            }
            RebindTreeView();
        }

        public static void RemoveUserRef(object sender, EventArgs e)
        {
            var userRef = GetMouseClickTargetModel<RdpUserRef>();
            var server = GetMouseClickTargetParentModel<RdpServer>();
            if (server.Users.Contains(userRef))
            {
                server.Users.Remove(userRef);
            }
            RebindTreeView();
        }

        #endregion

        public static void RebindTreeView()
        {
            if (MainForm.InvokeRequired)
            {
                MainForm.Invoke(new VoidDelegate(MainForm.RebindTree));
            }
            else
            {
                MainForm.RebindTree();
            }
        }

        public static void Connect(object sender, EventArgs e, RdpSetting setting)
        {
            if (MainForm.SelectedNode.Tag is RdpServerRef)
            {
                var serverRef = GetMouseClickTargetModel<RdpServerRef>();
                var user = GetMouseClickTargetParentModel<RdpUser>();
                AddSession(user, (RdpServer)serverRef.Ref, setting);
            }
            else if (MainForm.SelectedNode.Tag is RdpUserRef)
            {
                var userRef = GetMouseClickTargetModel<RdpUserRef>();
                var server = GetMouseClickTargetParentModel<RdpServer>();
                AddSession((RdpUser)userRef.Ref, server, setting);
            }
            else if (MainForm.SelectedNode.Tag is RdpSession)
            {
                var session = GetMouseClickTargetModel<RdpSession>();
                session.Connect();
            }
        }

        public static void AddSession(RdpUser user, RdpServer server, RdpSetting setting)
        {
            var session = RdpContext.Sessions.Values.SingleOrDefault(s => s.With(server, user));
            if (session == null)
            {
                session = new RdpSession(server, user);
                RdpContext.AddSession(session);
                if (MainForm.InvokeRequired)
                {
                    MainForm.Invoke(new ControlDelegate(MainForm.AddSession), session);
                }
                else
                {
                    MainForm.AddSession(session);
                }
            }
            session.Connect(setting);
            RebindTreeView();
        }

        private static T GetMouseClickTargetModel<T>()
        {
            return (T)MainForm.SelectedNode.Tag;
        }

        private static T GetMouseClickTargetParentModel<T>()
        {
            return (T)MainForm.SelectedNode.Parent.Tag;
        }
    }
}
